Switch to an extended form of _NET_WM_SYNC_REQUEST_COUNTER
authorOwen W. Taylor <otaylor@fishsoup.net>
Tue, 18 Sep 2012 13:31:17 +0000 (09:31 -0400)
committerOwen W. Taylor <otaylor@fishsoup.net>
Thu, 14 Feb 2013 22:19:48 +0000 (17:19 -0500)
By exporting two XSync counters on a toplevel window, we subscribe
to an extended form of the _NET_WM_SYNC_REQUEST_COUNTER protocol,
where the window manager can initiate an atomic frame, as previously,
but the application can also do so by incrementing the new counter to
an odd value, and then to an even value to finish the frame.

See:
https://mail.gnome.org/archives/wm-spec-list/2011-October/msg00006.html

The support for 64-bit integers that GLib requires is used to
simplify the logic.

https://bugzilla.gnome.org/show_bug.cgi?id=685460

gdk/x11/gdkdisplay-x11.c
gdk/x11/gdkwindow-x11.c
gdk/x11/gdkwindow-x11.h

index 20bde58a80c19f2aa0290582bf6898d79d351ea0..5af36d278feaf7f37a7db5645c21bfb94f97250b 100644 (file)
@@ -747,10 +747,10 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
         }
 
 #ifdef HAVE_XSYNC
-      if (!is_substructure && toplevel && display_x11->use_sync && !XSyncValueIsZero (toplevel->pending_counter_value))
+      if (!is_substructure && toplevel && display_x11->use_sync && toplevel->pending_counter_value != 0)
        {
-         toplevel->current_counter_value = toplevel->pending_counter_value;
-         XSyncIntToValue (&toplevel->pending_counter_value, 0);
+         toplevel->configure_counter_value = toplevel->pending_counter_value;
+         toplevel->pending_counter_value = 0;
        }
 #endif
 
@@ -1126,9 +1126,7 @@ _gdk_wm_protocols_filter (GdkXEvent *xev,
       if (toplevel)
        {
 #ifdef HAVE_XSYNC
-         XSyncIntsToValue (&toplevel->pending_counter_value,
-                           xevent->xclient.data.l[2],
-                           xevent->xclient.data.l[3]);
+         toplevel->pending_counter_value = xevent->xclient.data.l[2] + ((gint64)xevent->xclient.data.l[3] << 32);
 #endif
        }
       return GDK_FILTER_REMOVE;
index e86a73322ce8b1444de9b121bad1e498b29ed18c..6b8a0e8fab3d8757ca74766921506e57df17ea7b 100644 (file)
@@ -200,6 +200,19 @@ _gdk_x11_window_update_size (GdkWindowImplX11 *impl)
     }
 }
 
+static void
+set_sync_counter(Display     *display,
+                XSyncCounter counter,
+                 gint64       value)
+{
+    XSyncValue sync_value;
+
+    XSyncIntsToValue(&sync_value,
+                     value & G_GINT64_CONSTANT(0xFFFFFFFF),
+                     value >> 32);
+    XSyncSetCounter(display, counter, sync_value);
+}
+
 /*****************************************************
  * X11 specific implementations of generic functions *
  *****************************************************/
@@ -612,20 +625,24 @@ ensure_sync_counter (GdkWindow *window)
          Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
          XSyncValue value;
          Atom atom;
+         XID counters[2];
 
          XSyncIntToValue (&value, 0);
          
          toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
+         toplevel->extended_update_counter = XSyncCreateCounter (xdisplay, value);
          
          atom = gdk_x11_get_xatom_by_name_for_display (display,
                                                        "_NET_WM_SYNC_REQUEST_COUNTER");
-         
+
+         counters[0] = toplevel->update_counter;
+         counters[1] = toplevel->extended_update_counter;
          XChangeProperty (xdisplay, GDK_WINDOW_XID (window),
                           atom, XA_CARDINAL,
                           32, PropModeReplace,
-                          (guchar *)&toplevel->update_counter, 1);
+                          (guchar *)counters, 2);
          
-         XSyncIntToValue (&toplevel->current_counter_value, 0);
+         toplevel->current_counter_value = 0;
        }
     }
 #endif
@@ -1006,7 +1023,7 @@ gdk_toplevel_x11_free_contents (GdkDisplay *display,
                           toplevel->update_counter);
       toplevel->update_counter = None;
 
-      XSyncIntToValue (&toplevel->current_counter_value, 0);
+      toplevel->current_counter_value = 0;
     }
 #endif
 }
@@ -4863,13 +4880,21 @@ gdk_x11_window_configure_finished (GdkWindow *window)
 
       if (toplevel && toplevel->update_counter != None &&
          GDK_X11_DISPLAY (display)->use_sync &&
-         !XSyncValueIsZero (toplevel->current_counter_value))
+         toplevel->configure_counter_value != 0)
        {
-         XSyncSetCounter (GDK_WINDOW_XDISPLAY (window), 
-                          toplevel->update_counter,
-                          toplevel->current_counter_value);
-         
-         XSyncIntToValue (&toplevel->current_counter_value, 0);
+         set_sync_counter (GDK_WINDOW_XDISPLAY (window),
+                           toplevel->update_counter,
+                           toplevel->configure_counter_value);
+
+         toplevel->current_counter_value = toplevel->configure_counter_value;
+         if ((toplevel->current_counter_value % 2) == 1)
+           toplevel->current_counter_value += 1;
+
+         toplevel->configure_counter_value = 0;
+
+         set_sync_counter (GDK_WINDOW_XDISPLAY (window),
+                           toplevel->extended_update_counter,
+                           toplevel->current_counter_value);
        }
     }
 #endif
index 3dde77767d6e2874d4592e1813c631bb38a0e1a2..b4b737604bcc0293d72e30d0760d6a0a2a4d81ff 100644 (file)
@@ -144,11 +144,13 @@ struct _GdkToplevelX11
  
 #ifdef HAVE_XSYNC
   XID update_counter;
-  XSyncValue pending_counter_value; /* latest _NET_WM_SYNC_REQUEST value received */
-  XSyncValue current_counter_value; /* Latest _NET_WM_SYNC_REQUEST value received
-                                    * where we have also seen the corresponding
-                                    * ConfigureNotify
-                                    */
+  XID extended_update_counter;
+  gint64 pending_counter_value; /* latest _NET_WM_SYNC_REQUEST value received */
+  gint64 configure_counter_value; /* Latest _NET_WM_SYNC_REQUEST value received
+                                * where we have also seen the corresponding
+                                * ConfigureNotify
+                                */
+  gint64 current_counter_value;
 #endif
 };